﻿using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using HandyControl.Controls;
using HandyControl.Tools.Extension;
using SSHTool.Model;
using SSHTool.Service;
using SSHTool.Util;
using SSHTool.View;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Input;

namespace SSHTool.ViewModel
{
    public class CmdViewModel : ObservableObject
    {
        private SshService sshService;
        private CmdLogService logService;
        public CmdViewModel(SshService sshService, CmdLogService logService)
        {
            this.sshService = sshService;
            this.logService = logService;
        }

        private int cmdIndex = -1;
        private List<CmdLogModel> cmdLogList = new List<CmdLogModel>();
        private Dictionary<string, int> keywordMap = new Dictionary<string, int>();

        private string _output;

        public string Output { get => _output; set => SetProperty(ref _output, value); }

        private string _cmd;

        public string Cmd { get => _cmd; set => SetProperty(ref _cmd, value); }

        private string richText;
        public string RichText { get => richText; set => SetProperty(ref richText, value); }

        private bool clearFlag;

        public bool ClearFlag { get => clearFlag; set => SetProperty(ref clearFlag, value); }


        private ConnectionViewModel _connection;

        public ConnectionViewModel Connection
        {
            get => _connection;
            set
            {
                SetProperty(ref _connection, value);
            }
        }

        public void Init()
        {
            cmdLogList = logService.GetList(_connection.Id);
            cmdIndex = GetMaxCmdIndex();

            sshService?.Connect(_connection);
            sshService?.Run(Constant.CMD_DATE);
            sshService.Run(Constant.CMD_LS_ALL);
        }

        public void SetCode(string code)
        {
            if (sshService != null)
            {
                sshService.Code = code;
            }
        }

        public void SetText(string text)
        {
            if (string.IsNullOrEmpty(text))
            {
                return;
            }

            RichText = text;
        }

        public void Disconnect()
        {
            sshService?.Disconnect();
        }

        public RelayCommand<KeyEventArgs> CmdKeyUpCmd => new RelayCommand<KeyEventArgs>(CmdKeyUp);

        public RelayCommand<KeyEventArgs> CmdKeyDownCmd => new RelayCommand<KeyEventArgs>(CmdKeyDown);

        public RelayCommand OpenFilePageCmd => new RelayCommand(OpenFilePage);

        private async void OpenFilePage()
        {
            var vm = App.GetService<FileMgrViewModel>();
            var page = App.GetService<FilePage>();
            page.DataContext = vm;

            vm.Init(Connection.Id, sshService);

            await Dialog.Show(page).GetResultAsync<int>();
        }

        private void CmdKeyDown(KeyEventArgs args)
        {
            if (args.Key == Key.Tab)
            {
                var list = sshService?.GetNameList();

                if (!StringUtil.IsEmpty(list))
                {
                    string cmdText = GetCmdTipString(list);

                    if (!string.IsNullOrEmpty(cmdText))
                    {
                        Cmd = cmdText;
                        //Growl.Info(cmdText);
                    }
                }

                if (args.Source is HandyControl.Controls.TextBox box)
                {
                    box.Focus();
                }
            }
        }

        private void CmdKeyUp(KeyEventArgs args)
        {
            if (args.Key == Key.Enter)
            {
                if (string.IsNullOrEmpty(Cmd))
                {
                    Growl.Warning("请输入命令");
                    return;
                }

                string cmd = Cmd;

                Cmd = "";

                switch (cmd)
                {
                    case Constant.CMD_CLEAR:
                    case Constant.CMD_CLS:
                        ClearFlag = false;
                        ClearFlag = true;
                        break;
                    default:
                        bool flag = sshService.Run(cmd);
                        if (flag)
                        {
                            logService.UpdateConnectionId(_connection.Id).AddCmd(cmd, cmdLogList);
                            cmdIndex = GetMaxCmdIndex();
                        }
                        break;
                }

            }
            else if (args.Key == Key.Tab)
            {
                var list = sshService?.GetNameList();

                if (StringUtil.IsEmpty(list))
                {
                    return;
                }

                string cmdText = GetCmdTipString(list);

                if (string.IsNullOrEmpty(cmdText))
                {
                    return;
                }

                Cmd = cmdText;
            }
            else if (args.Key == Key.Up)
            {
                if (cmdIndex < 0)
                {
                    cmdIndex = GetMaxCmdIndex();
                }

                string cmd = logService.GetCmd(cmdIndex, cmdLogList);

                if (!string.IsNullOrEmpty(cmd))
                {
                    Cmd = cmd;
                }

                cmdIndex--;
            }
            else if (args.Key == Key.Down)
            {
                if (cmdIndex >= cmdLogList.Count)
                {
                    cmdIndex = 0;
                }

                string cmd = logService.GetCmd(cmdIndex, cmdLogList);

                if (!string.IsNullOrEmpty(cmd))
                {
                    Cmd = cmd;
                }

                cmdIndex++;
            }
        }

        private int GetMaxCmdIndex()
        {
            if (cmdLogList == null)
            {
                return -1;
            }

            if (cmdLogList.Count > 0)
            {
                return cmdLogList.Count - 1;
            }

            return -1;
        }

        private string GetCmdTipString(List<string> list)
        {
            if (StringUtil.IsEmpty(list))
            {
                return null;
            }

            string cmd = Cmd;

            int index = -1;
            if (keywordMap.ContainsKey(cmd))
            {
                index = keywordMap[cmd];
            }
            else
            {
                keywordMap.Add(cmd, index);
            }

            var newList = list.Where(m => m.StartsWith(cmd)).ToList();

            if (StringUtil.IsEmpty(newList))
            {
                return null;
            }

            string cmdText = null;
            if (index + 1 < newList.Count)
            {
                index++;
                cmdText = newList[index];
            }
            else
            {
                index = 0;
                cmdText = newList[0];
            }

            keywordMap[cmd] = index;
            return cmdText;
        }
    }
}
